package com.cardgame;

import java.util.Collections;
import java.util.Hashtable;
import java.util.Vector;

import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;

import com.cardgame.cards.Card;
import com.cardgame.cards.Deck;
import com.cardgame.constants.Constants;
import com.player.Player;

@SuppressWarnings("unchecked")
public class GameView extends SurfaceView implements SurfaceHolder.Callback {

	Activity myActivity;
	
	ImageButton okButton;
	ImageButton cancelButton;
	ImageButton skill1;
	ImageButton skill2;
	ImageButton endButton;
	ImageView animation;
	
	ImageButton myCard1;
	ImageButton myCard2;
	ImageButton myCard3;
	ImageButton myCard4;
	ImageButton myCard5;
	ImageButton myCard6;
	ImageButton myCard7;
	ImageButton myCard8;
	
	Vector cardButtons = new Vector();
	
	Deck deck;
	
	//store the cards currently in hand
	Vector inHands;
	
	//find the corresponding picture for each card, skills hp etc,
	Hashtable cardActive;
	Hashtable cardInactive;
	Hashtable hpImages;
	Hashtable cardNumberImages;
	Hashtable animationImages;
	Hashtable skillActive;
	Hashtable skillInActive;
	Hashtable playerActive1;
	Hashtable playerInactive1;
	Hashtable playerActive2;
	Hashtable playerInactive2;
	Hashtable playerDead;
	Hashtable diceImages;
	
	Player oldSelected = null;
	
	//contains the images for the cards currently in hand
	Vector cardImages = new Vector();
	
	//stores all the player in the order of play
	Vector playerOrder = new Vector();
	//Vector playerOrderClone;
	
	//temporary vector to store the cards that will be discarded
	Vector cardsToDiscard = new Vector();
	
	//the flag that is used for drawing animation
	boolean drawFlag = true;
	
	//show animiation for the first time
	boolean showfirst = true;
	
	//each player can normally only use 1 weapon 
	boolean hasAttacked = false;
	
	//used to limit some use of skills to once per turn
	boolean skill1Used = false;
 	boolean skill2Used = false;
	
	//if the user can retaliate
	String retaliateFlag;
	
	Drawable cardDrawable;
	
	//backgroup image 
	Bitmap mBackgroundImage;
	
	//the index that shows who's turn it is
	int currentPlayer = -1;
	
	//the card that attacked the player
	String attackCard = "";
	
	//the text that shows the interaction between players.
	String battleText;
	Paint textPaint = new Paint();
	
	// the name that identify the player who is playing this game on this Android
	Player me;
	int myIndex = -1;
	
	//the current card that has been selected
	int selectCardIndex = -1;
	
	//the distance between the current player and the target player
	int distance = -1;
	
	//the roll result for spell card SizeMatters
	int sizeResult = 0;
	
	//the roll results used for retrieve images
	int diceResult = 0;
	
	//the count used to count the number of attacks for assassin 
	int assassinCount = 2;
	
	//the total damage dealt to the enemy team in one turn
	int damageDealt = 0;
	
	//the current phase of the game
	String currentPhase;
	
	Player actioner;
	Player skullTarget;
	String actioncard;
	
	Resources mRes;
	Context mContext;
	GameThread thread;
	
	MediaPlayer backgroundMusic;

	public GameView(Context context, AttributeSet attrs) {
	        super(context, attrs);
	        setFocusable(true);
	        setFocusableInTouchMode(true);
	        
	        mContext = context;
	        mRes = context.getResources();

	        mBackgroundImage = BitmapFactory.decodeResource(mRes, R.drawable.bg1);

	    	battleText = " ";
	    	
	    	
	     // register our interest in hearing about changes to our surface
	        SurfaceHolder holder = getHolder();
	        holder.addCallback(this);

	        thread = new GameThread(holder, context, new Handler() {
	            @Override
	            public void handleMessage(Message m) {
	            	if(thread.mMode == thread.STATE_LOSE)
	            	{
	            		endButton.setImageResource(R.drawable.endlose);
	            	}
	            	else if(thread.mMode == thread.STATE_DRAW)
	            	{
	            		endButton.setImageResource(R.drawable.enddraw);
	            	}
	            	else if(thread.mMode == thread.STATE_WIN)
	            	{
	            		endButton.setImageResource(R.drawable.endwin);
	            	}
	        		endButton.setVisibility(View.VISIBLE);
	            }
	        });
	 }

	public GameThread getThread()
	{
		return thread;
	}

	public void setMe(Player player)
	{
		me = player;
	}

	public void setActivity(Activity act)
	{
		myActivity = act;
		
		for(int p=0; p<playerOrder.size(); p++)
		{
	    	((Player)playerOrder.get(p)).setMyActivity(myActivity);
		}
	}
	
	public void init() {

		textPaint.setAntiAlias(true);
        textPaint.setTextSize(11);
        textPaint.setColor(Color.WHITE);
        
		deck = new Deck();
		deck.initDeck();
		
		initHashtable();
		
		for(int p=0; p<playerOrder.size(); p++)
        {
        	((Player)playerOrder.get(p)).setmRes(mRes);
        }
		
		myIndex = findIndex(me.getName(), playerOrder);
		
		//TODO: may need this later
        //playerOrderClone = (Vector)playerOrder.clone();
		
		inHands = new Vector();
		for (int j = 0; j < playerOrder.size(); j ++)
		{
			Vector tmpVector = new Vector();
			for(int i = 0; i < Constants.InitialCardNumber; i++)
			{
				Card tmpCard = deck.getNextCard();
				tmpVector.add(tmpCard);
			}
			
			if(j == myIndex)
				inHands = tmpVector;
			((Player)playerOrder.get(j)).setInHands(tmpVector);
		}
		
		setSkillImage();
		setCardImages();
		 
		currentPhase = Constants.drawingPhase;
		currentPlayer = 0;
		
		battleText = ((Player)playerOrder.get(currentPlayer)).getpClass() + mRes.getString(R.string.drawPhase);
		
		//play the background music here
		//TODO: add music later
		
		/*backgroundMusic = MediaPlayer.create(mContext, R.raw.background);
		backgroundMusic.setLooping(true);
		backgroundMusic.start();*/
	}
	
	//set the backgroud images for skill buttons
	private void setSkillImage()
	{
    	myActivity.runOnUiThread(new Runnable()
		{
			public void run(){
				skill1.setBackgroundDrawable(mRes.getDrawable((Integer)skillActive.get(me.getSkill1())));
				skill2.setBackgroundDrawable(mRes.getDrawable((Integer)skillActive.get(me.getSkill2())));
			}
		});
	}
	
	//set images to the cards currently in the hand
	private void setCardImages()
	{	
		cardImages = new Vector();
		for (int i = 0; i < inHands.size(); i++)
		{
	    	Card tmpCard = (Card)inHands.get(i);
	    	String cardName = tmpCard.getName();
	    	
	    	if(tmpCard.getSelected())
	    		cardDrawable = mRes.getDrawable((Integer)cardActive.get(cardName));
	    	else cardDrawable = mRes.getDrawable((Integer)cardInactive.get(cardName));
	    	
	    	cardImages.add(cardDrawable);
		}

		myActivity.runOnUiThread(new Runnable()
		{
			public void run(){
				for(int i = 0; i < cardButtons.size(); i++)
				{
					if(i < cardImages.size())
					{
						((ImageButton)cardButtons.elementAt(i)).setBackgroundDrawable((Drawable)cardImages.elementAt(i));
					}
					else{
						((ImageButton)cardButtons.elementAt(i)).setBackgroundDrawable(null);
					}
				}
			}
		});
    }
	
	private void updateCardNumberImage()
	{
		myActivity.runOnUiThread(new Runnable()
		{
			public void run(){
				for(int i = 0; i < playerOrder.size(); i++)
				{
					if(((Player)(playerOrder.get(i))).getCardNumber() != null)
						((Player)(playerOrder.get(i))).getCardNumber().setBackgroundDrawable(mRes.getDrawable((Integer)cardNumberImages.get(((Player)(playerOrder.get(i))).getInHands().size())));
				}
			}
		});
	}
	
	private void updateActionImage()
	{
		myActivity.runOnUiThread(new Runnable()
		{
			public void run(){
				if(actioner != null && actioncard != null)
				{
					actioner.getAction().setBackgroundDrawable(mRes.getDrawable((Integer)cardActive.get(actioncard)));
					animation.setBackgroundDrawable(mRes.getDrawable((Integer)animationImages.get(actioncard)));
					
					actioncard = null;
				}
			}
		});
		
		updateCardNumberImage();
		if(currentPlayer == myIndex && actioner != me)
		{
			mySleep();
		}
		else{
			mySleep();
		}
	}
	
	private void updateDiceImage()
	{
		myActivity.runOnUiThread(new Runnable()
		{
			public void run(){
				if(actioner != null && diceResult != 0)
				{
					actioner.getAction().setBackgroundDrawable(mRes.getDrawable((Integer)diceImages.get(diceResult)));
					diceResult = 0;
				}
			}
		});
		
		if(currentPlayer == myIndex)
		{
			mySleep();
		}
		else{
			mySleep();
		}
	}
	
	private void updateSkullImage()
	{
		myActivity.runOnUiThread(new Runnable()
		{
			public void run(){
				if(skullTarget != null)
				{
					skullTarget.getAction().setBackgroundDrawable(mRes.getDrawable(R.drawable.skull));
				}
			}
		});
		
		if(currentPlayer == myIndex)
		{
			mySleep();
		}
		else{
			mySleep();
		}
	}
	
	private void clearActionImage()
	{
		myActivity.runOnUiThread(new Runnable()
		{
			public void run(){
				for (int i = 0; i < playerOrder.size(); i ++)
				{
					((Player)playerOrder.get(i)).getAction().setBackgroundDrawable(null);
				}
				animation.setBackgroundDrawable(null);
			}
		});
	}
	
	//update the hp image to reflect the current hp
	private void updateHPImage()
	{
		myActivity.runOnUiThread(new Runnable()
		{
			public void run(){
				for (int i = 0; i < playerOrder.size(); i ++)
				{
					if(((Player)playerOrder.get(i)).getCurrentHP() > 0)
						((Player)playerOrder.get(i)).getHpImage().setBackgroundDrawable(mRes.getDrawable((Integer)hpImages.get(((Player)playerOrder.get(i)).getCurrentHP())));
					else 
						((Player)playerOrder.get(i)).getHpImage().setBackgroundDrawable(null);
				}
			}
		});
	}
	
	//disable all the clickable button when the player dies
	private void disableButtons()
	{
		myActivity.runOnUiThread(new Runnable()
		{
			public void run(){
				okButton.setClickable(false);
				cancelButton.setClickable(false);
				skill1.setClickable(false);
				skill1.setBackgroundDrawable(null);
				skill2.setClickable(false);
				skill2.setBackgroundDrawable(null);
				
				myCard1.setClickable(false);
				myCard1.setBackgroundDrawable(null);
				myCard2.setClickable(false);
				myCard2.setBackgroundDrawable(null);
				myCard3.setClickable(false);
				myCard3.setBackgroundDrawable(null);
				myCard4.setClickable(false);
				myCard4.setBackgroundDrawable(null);
				myCard5.setClickable(false);
				myCard5.setBackgroundDrawable(null);
				myCard6.setClickable(false);
				myCard6.setBackgroundDrawable(null);
				myCard7.setClickable(false);
				myCard7.setBackgroundDrawable(null);
				myCard8.setClickable(false);
				myCard8.setBackgroundDrawable(null);
			}
		});
	}
	
	//find the index of a particular player in the playorder vector
	public int findIndex(String strName, Vector v)
	{
		for(int i = 0; i < v.size(); i ++)
		{
			String name = ((Player)v.get(i)).getName();
			if(name.compareTo(strName) == 0)
			{
				return i;
			}
		}
		
		return -1;
	}
	
	
	//calculate the distance between two players
	private int calcDist(Player p1, Player p2)
	{
		int p1Index = 0;
		int p2Index = 0;
		int dist = 0;
		
		if (p1.getSkill1() == Constants.skill1)
		{
			return 0;
		}
		
		p1Index = findIndex(p1.getName(), playerOrder);
		p2Index = findIndex(p2.getName(), playerOrder);
		
		dist = Math.abs(p1Index - p2Index);
		if(dist > (playerOrder.size() / 2)) dist -= playerOrder.size();
		
		return Math.abs(dist);
	}
	
	//initialise the table which stores the name/image value pair for each card
	private void initHashtable()
	{
		cardInactive = new Hashtable();
		cardInactive.put(Constants.SwordName, R.drawable.sword_inactive);
		cardInactive.put(Constants.SpearName, R.drawable.spear_inactive);
		cardInactive.put(Constants.BowName, R.drawable.bow_inactive);
		cardInactive.put(Constants.ShieldName, R.drawable.shield_inactive);
		cardInactive.put(Constants.PotionName, R.drawable.potion_inactive);
		cardInactive.put(Constants.AmageddonName, R.drawable.amageddon_inactive);
		cardInactive.put(Constants.InvasionName, R.drawable.monsterinvastion_inactive);
		cardInactive.put(Constants.RevelationName, R.drawable.revelation_inactive);
		cardInactive.put(Constants.FateName, R.drawable.fate_inactive);
		cardInactive.put(Constants.PoisonName, R.drawable.poison_inactive);
		cardInactive.put(Constants.GenerosityName, R.drawable.generosity_inactive);
		cardInactive.put(Constants.TruceName, R.drawable.truce_inactive);
		cardInactive.put(Constants.SilenceName, R.drawable.silence_inactive);
		cardInactive.put(Constants.SpiritName, R.drawable.ethereal_inactive);
		cardInactive.put(Constants.HexName, R.drawable.hex_inactive);
		cardInactive.put(Constants.NegationName, R.drawable.negation_inactive);
		cardInactive.put(Constants.CurseName, R.drawable.curse_inactive);
		cardInactive.put(Constants.DoubleEdgeName, R.drawable.doubleedge_inactive);
		cardInactive.put(Constants.RouletteName, R.drawable.roulette_inactive);
		cardInactive.put(Constants.WheelName, R.drawable.wheeloffortune_inactive);
		cardInactive.put(Constants.SizeMattersName, R.drawable.sizematters_inactive);
		cardInactive.put(Constants.ShallowName, R.drawable.shallowgrave_inactive);
		
		cardActive = new Hashtable();
		cardActive.put(Constants.SwordName, R.drawable.sword_active);
		cardActive.put(Constants.SpearName, R.drawable.spear_active);
		cardActive.put(Constants.BowName, R.drawable.bow_active);
		cardActive.put(Constants.ShieldName, R.drawable.shield_active);
		cardActive.put(Constants.PotionName, R.drawable.potion_active);
		cardActive.put(Constants.AmageddonName, R.drawable.amageddon_active);
		cardActive.put(Constants.InvasionName, R.drawable.monsterinvastion_active);
		cardActive.put(Constants.RevelationName, R.drawable.revelation_active);
		cardActive.put(Constants.FateName, R.drawable.fate_active);
		cardActive.put(Constants.PoisonName, R.drawable.poison_active);
		cardActive.put(Constants.GenerosityName, R.drawable.generosity_active);
		cardActive.put(Constants.TruceName, R.drawable.truce_active);
		cardActive.put(Constants.SilenceName, R.drawable.silence_active);
		cardActive.put(Constants.SpiritName, R.drawable.ethereal_active);
		cardActive.put(Constants.HexName, R.drawable.hex_active);
		cardActive.put(Constants.NegationName, R.drawable.negation_active);
		cardActive.put(Constants.CurseName, R.drawable.curse_active);
		cardActive.put(Constants.DoubleEdgeName, R.drawable.doubleedge_active);
		cardActive.put(Constants.RouletteName, R.drawable.roulette_active);
		cardActive.put(Constants.WheelName, R.drawable.wheeloffortune_active);
		cardActive.put(Constants.SizeMattersName, R.drawable.sizematters_active);
		cardActive.put(Constants.ShallowName, R.drawable.shallowgrave_active);
		
		hpImages = new Hashtable();
		hpImages.put(1, R.drawable.health1);
		hpImages.put(2, R.drawable.health2);
		hpImages.put(3, R.drawable.health3);
		hpImages.put(4, R.drawable.health4);
		hpImages.put(5, R.drawable.health5);
		
		diceImages = new Hashtable();
		diceImages.put(1, R.drawable.dice_1);
		diceImages.put(2, R.drawable.dice_2);
		diceImages.put(3, R.drawable.dice_3);
		diceImages.put(4, R.drawable.dice_4);
		diceImages.put(5, R.drawable.dice_5);
		diceImages.put(6, R.drawable.dice_6);
		
		cardNumberImages = new Hashtable();
		cardNumberImages.put(0, R.drawable.card0);
		cardNumberImages.put(1, R.drawable.card1);
		cardNumberImages.put(2, R.drawable.card2);
		cardNumberImages.put(3, R.drawable.card3);
		cardNumberImages.put(4, R.drawable.card4);
		cardNumberImages.put(5, R.drawable.card5);
		cardNumberImages.put(6, R.drawable.card6);
		cardNumberImages.put(7, R.drawable.card7);
		cardNumberImages.put(8, R.drawable.card8);
		
		animationImages = new Hashtable();
		animationImages.put(Constants.SwordName, R.drawable.sword_animation);
		animationImages.put(Constants.SpearName, R.drawable.spear_animation);
		animationImages.put(Constants.BowName, R.drawable.bow_animation);
		animationImages.put(Constants.ShieldName, R.drawable.shield_animation);
		animationImages.put(Constants.PotionName, R.drawable.potion_animation);
		animationImages.put(Constants.AmageddonName, R.drawable.amageddon_animation);
		animationImages.put(Constants.InvasionName, R.drawable.monsterinvastion_animation);
		animationImages.put(Constants.RevelationName, R.drawable.revelation_animation);
		animationImages.put(Constants.FateName, R.drawable.fate_animation);
		animationImages.put(Constants.PoisonName, R.drawable.poison_animation);
		animationImages.put(Constants.GenerosityName, R.drawable.generosity_animation);
		animationImages.put(Constants.TruceName, R.drawable.truce_animation);
		animationImages.put(Constants.SilenceName, R.drawable.silence_animation);
		animationImages.put(Constants.SpiritName, R.drawable.ethereal_animation);
		animationImages.put(Constants.HexName, R.drawable.hex_animation);
		animationImages.put(Constants.NegationName, R.drawable.negation_animation);
		animationImages.put(Constants.CurseName, R.drawable.curse_animation);
		animationImages.put(Constants.DoubleEdgeName, R.drawable.doubleedge_animation);
		animationImages.put(Constants.RouletteName, R.drawable.roulette_animation);
		animationImages.put(Constants.WheelName, R.drawable.wheeloffortune_animation);
		animationImages.put(Constants.SizeMattersName, R.drawable.sizematters_animation);
		animationImages.put(Constants.ShallowName, R.drawable.shallowgrave_animation);
		
		skillActive = new Hashtable();
		skillActive.put(Constants.skill1, R.drawable.farreaching_active);
		skillActive.put(Constants.skill2, R.drawable.wisdom_active);
		skillActive.put(Constants.skill3, R.drawable.prediction_active);
		skillActive.put(Constants.skill4, R.drawable.immunity_active);
		skillActive.put(Constants.skill5, R.drawable.paralyze_active);
		skillActive.put(Constants.skill6, R.drawable.spellresistance_active);
		skillActive.put(Constants.skill7, R.drawable.bloodthirst_active);
		skillActive.put(Constants.skill8, R.drawable.nightmare_active);
		skillActive.put(Constants.skill9, R.drawable.transformation_active);
		skillActive.put(Constants.skill10, R.drawable.creation_active);
		skillActive.put(Constants.skill11, R.drawable.warcry_active);
		skillActive.put(Constants.skill12, R.drawable.counterattack_active);
		skillActive.put(Constants.skill13, R.drawable.illustion_active);
		skillActive.put(Constants.skill14, R.drawable.impersonate_active);
		skillActive.put(Constants.skill17, R.drawable.healing_active);
		skillActive.put(Constants.skill18, R.drawable.seekprotection_active);
		skillActive.put(Constants.skill19, R.drawable.archery_active);
		skillActive.put(Constants.skill20, R.drawable.safedistance_active);
		skillActive.put(Constants.skill21, R.drawable.sacrifice_active);
		skillActive.put(Constants.skill22, R.drawable.defender_active);
		skillActive.put(Constants.skill23, R.drawable.instigation_active);
		skillActive.put(Constants.skill24, R.drawable.assassinate_active);
		skillActive.put(Constants.skill25, R.drawable.charm_active);
		skillActive.put(Constants.skill26, R.drawable.lullaby_active);
		skillActive.put(Constants.skill27, R.drawable.revenge_active);
		skillActive.put(Constants.skill28, R.drawable.eyeforaneye_active);
		
		playerDead = new Hashtable();
		playerDead.put(Constants.classAlchemist, R.drawable.alchemist_dead);
		playerDead.put(Constants.classAssassin, R.drawable.assassin_dead);
		playerDead.put(Constants.classAvenger, R.drawable.avenger_dead);
		playerDead.put(Constants.classBard, R.drawable.bard_dead);
		playerDead.put(Constants.classFighter, R.drawable.warrior_dead);
		playerDead.put(Constants.classIllusionist, R.drawable.illusionist_dead);
		playerDead.put(Constants.classPaladin, R.drawable.paladin_dead);
		playerDead.put(Constants.classPriestess, R.drawable.priestess_dead);
		playerDead.put(Constants.classProphet, R.drawable.prophet_dead);
		playerDead.put(Constants.classRanger, R.drawable.ranger_dead);
		playerDead.put(Constants.classSage, R.drawable.sage_dead);
		playerDead.put(Constants.classSorceress, R.drawable.sorceress_dead);
		playerDead.put(Constants.classVampire, R.drawable.vampire_dead);
	}
	
	
	public void setPlayerOrder(Vector v)
	{
		playerOrder = v;
	}
	
    class GameThread extends Thread
    {
        public final int STATE_LOSE = 1;
        public final int STATE_PAUSE = 2;
        public final int STATE_DRAW = 3;
        public final int STATE_RUNNING = 4;
        public final int STATE_WIN = 5;
        
        private SurfaceHolder mSurfaceHolder;
        private Handler mHandler;
        
    	private boolean mRun = false;

        /** The state of the game. One of READY, RUNNING, PAUSE, LOSE, or WIN */
        private int mMode;

    	public GameThread(SurfaceHolder surfaceHolder, Context context, Handler handler) {
    		
            mSurfaceHolder = surfaceHolder;
            mHandler = handler;

    	}

    	/**
         * Pauses the physics update & animation.
         */
        public void pause() {
            synchronized (mSurfaceHolder) {
                if (mMode == STATE_RUNNING) setState(STATE_PAUSE);
            }
        }
        
    	
    	//TODO: update layout
    	private void doDraw(Canvas canvas) {

    		canvas.drawBitmap(mBackgroundImage, 0, 0, null);

    		canvas.drawText(battleText, 110, 217, textPaint);  
    	}

    	//TODO: may need animation
    	private void doDrawAnimation()
    	{
    		drawFlag = false;
    		
    		if(myIndex == currentPlayer)
			{
				changePhase();
			}
    	}
    	
    	/**
         * the heart of the worker bee
         */
    	@Override
        public void run() {
        	
            while (mRun) {
                
                if (mMode == STATE_RUNNING) {
                		if (currentPhase == Constants.drawingPhase)
                		{		
                			checkEnd();
                			
                			if(drawFlag)
                			{
                				drawCard(currentPlayer);
                			}
                			if(currentPlayer == myIndex)
                			{
                				doDrawAnimation();
                			}
                			else{
                				mySleep();
                			}
                		}
                		else if(currentPhase == Constants.playPhase)
                		{
                			checkEnd();
                			drawFlag = true;
                			
                			Player p = (Player)playerOrder.get(currentPlayer);
                    		
                    		if(p.getPlayerState().contains(Constants.skipPlay))
                    		{
                    			p.getPlayerState().remove(Constants.skipPlay);
                    			changePhase();
                    		}
                    		
                    		else if(currentPlayer != myIndex)
                			{
                				//TODO may need to change this later
                				//This is mainly to give user a feeling that the enemy is thinking
                    			mySleep();
                				playAI();
                				changePhase();
                			}	
                		}
                		
                		else if(currentPhase == Constants.discardPhase)
                		{
                			if(currentPlayer != myIndex)
                			{
                				mySleep();
                				discardAI();
                				changePhase();
                			}	
                		}
                		
                }// end of STATE_RUNNING block
                
                Canvas c = null;
                try {
                    c = mSurfaceHolder.lockCanvas(null);
                    doDraw(c);
                    // }
                } finally {
                    // do this in a finally so that if an exception is thrown
                    // during the above, we don't leave the Surface in an
                    // inconsistent state
                    if (c != null) {
                        mSurfaceHolder.unlockCanvasAndPost(c);
                    }
                }// end finally block
            }// end while mrun block
       
    	}
    	
    	
    	//increase the cards in hand of a player by the drawing amount
    	//TODO: draw card animation
    	private void drawCard(int player)
    	{
    		int drawNumber = Constants.DrawCardNumber;
    		Player p = (Player)playerOrder.get(player);
    		
    		if(p.getPlayerState().contains(Constants.skipDraw))
    		{
    			p.getPlayerState().remove(Constants.skipDraw);
    			changePhase();
    			return;
    		}
    		
    		if(p.getSkill2() == Constants.skill2)
    		{
    			drawNumber++;
    		}
    		
    		Vector cardsInHand = p.getInHands();		
    		
    		for(int i = 0; i < drawNumber; i++)
    		{
    			Card tmpCard = deck.getNextCard();
				cardsInHand.add(tmpCard);
    		}

    		
    		p.setInHands(cardsInHand);
    		
    		if(myIndex == currentPlayer)
    		{
    			inHands = cardsInHand;   		
        		setCardImages();
    		}
    		
    		else changePhase();
    	}
        
        /**
         * Used to signal the thread whether it should be running or not.
         * Passing true allows the thread to run; passing false will shut it
         * down if it's already running. Calling start() after this was most
         * recently called with false will result in an immediate shutdown.
         * 
         * @param b true to run, false to shut down
         */
        public void setRunning(boolean b) {
            mRun = b;
        }
        
        public void setState(int mode) {
            mMode = mode;
        }
        
        /**
         * Resumes from a pause.
         */
        public void unpause() {
            setState(STATE_RUNNING);
        }


    }
    
    /*
     * Callback invoked when the Surface has been created and is ready to be
     * used.
     */
    public void surfaceCreated(SurfaceHolder holder) {
        // start the thread here so that we don't busy-wait in run()
        // waiting for the surface to be created
        thread.setRunning(true);
        thread.start();
    }

    /*
     * Callback invoked when the Surface has been destroyed and must no longer
     * be touched. WARNING: after this method returns, the Surface/Canvas must
     * never be touched again!
     */
    public void surfaceDestroyed(SurfaceHolder holder) {
        // we have to tell thread to shut down & wait for it to finish, or else
        // it might touch the Surface after we return and explode
        boolean retry = true;
        thread.setRunning(false);
        while (retry) {
            try {
                thread.join();
                retry = false;
            } catch (InterruptedException e) {
            }
        }
    }

    /* Callback invoked when the surface dimensions change. */
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
    }
    
    public void setButton(ImageButton b1, ImageButton b2, ImageButton b3, ImageButton b4, ImageView a, ImageButton v)
    {
    	okButton = b1;
    	cancelButton = b2;
    	skill1 = b3;
    	skill2 = b4;
    	endButton = v;
    	animation = a;
    	
    	setButtonListener();
    }
    
    
    public void setMyCards(ImageButton c1, ImageButton c2, ImageButton c3, ImageButton c4, ImageButton c5, ImageButton c6, ImageButton c7, ImageButton c8)
    {
    	myCard1 = c1;
    	myCard2 = c2;
    	myCard3 = c3;
    	myCard4 = c4;
    	myCard5 = c5;
    	myCard6 = c6;
    	myCard7 = c7;
    	myCard8 = c8;
    	
    	cardButtons.add(myCard1);
    	cardButtons.add(myCard2);
    	cardButtons.add(myCard3);
    	cardButtons.add(myCard4);
    	cardButtons.add(myCard5);
    	cardButtons.add(myCard6);
    	cardButtons.add(myCard7);
    	cardButtons.add(myCard8);
    	
    	setCardButtonListener();
    }

    private void setCardButtonListener()
    {

		myCard1.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	buttonAction(0);
            }
		});
		
		myCard2.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	buttonAction(1);
            }
		});
	
		myCard3.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	buttonAction(2);
            }
		});
		
		myCard4.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	buttonAction(3);
            }
		});
		
		myCard5.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	buttonAction(4);
            }
		});
		
		myCard6.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	buttonAction(5);
            }
		});
		
		myCard7.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	buttonAction(6);
            }
		});
		
		myCard8.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	buttonAction(7);
            }
		});
    }
    
	private void buttonAction(int position)
	{	
		if(position >= inHands.size())
			return;
		
    	Card cardInHand = (Card)inHands.get(position);
		cardInHand.setSelected(!cardInHand.getSelected());
		inHands.set(position, cardInHand);
		
		if(currentPhase != Constants.discardPhase)
		{
			if(selectCardIndex != -1 && selectCardIndex != position)
			{		
				Card oldCard = (Card)inHands.get(selectCardIndex);
				oldCard.setSelected(false);
				inHands.set(selectCardIndex, oldCard);
				selectCardIndex = position;				
			}
			else if(selectCardIndex == position)
			{
				selectCardIndex = -1;
			}
			else if(selectCardIndex == -1)
			{
				selectCardIndex = position;
			}
		}
		
		setCardImages();
	}
	
    private void setButtonListener()
    {
    	okButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	
            	clearActionImage(); 
            	
            	if(thread.mMode != thread.STATE_RUNNING)
            	{
            		return;
            	}
            	
            	if (selectCardIndex == -1 && currentPhase != Constants.discardPhase)
            	{
            		return;
            	}
            	
            	
            	if(currentPlayer != myIndex)
            	{
            		return;
            	}

            	
            	if(currentPhase == Constants.discardPhase)
            	{
            		Vector tmpV = new Vector();
            		
            		for (int i = 0; i < inHands.size(); i++)
            		{
            			if(((Card)inHands.get(i)).getSelected())
            			{
            				tmpV.add(i);
            			}
            		}
            		
            		if(tmpV.size() == (inHands.size() - Constants.AfterDiscardNumber))
            		{
            			Collections.sort(tmpV, Collections.reverseOrder());
            			for(int i = 0; i < tmpV.size(); i++)
            			{
            				inHands.remove(((Integer)tmpV.get(i)).intValue());
            			}
            			
            			setCardImages();
            			changePhase();
            		}
            	}
            	else{
                	actioner = me;
                	
            		if (selectCardIndex == -1)
            		{	
            			return;
            		}
            		
            		Card currentCard = (Card)inHands.get(selectCardIndex);
            		
            		if(currentCard.getType() == Constants.typeSpell && me.getPlayerState().contains(Constants.SilenceName))
            		{
            			battleText = "You can not use spell card this turn!";
            			return;
            		}
            		
            		if(currentCard.getType() == Constants.typeWeapon && me.getPlayerState().contains(Constants.SpiritName))
            		{
            			battleText = "You can not use weapon card this turn!";
            			return;
            		}
                	
            		if(currentCard.getTarget() == Constants.targetEnemy)
                	{
                		for(int i=0; i<playerOrder.size(); i++)
                		{
                			Player target = (Player)playerOrder.get(i);
                			
                			if(target.getSelected() && target.getTeam() != me.getTeam())
                			{
                				update(currentCard, me, target);
                				target.setSelected(false);
                				updatePlayerImage(target);
                				break;
                			}
                			
                			else if(target.getSelected()){
                				battleText = "Can not target teammate!"; 
                			}
                		}
                	}
                	else if(currentCard.getTarget() == Constants.targetSelf)
                	{
                		update(currentCard, me, me);
                	}
                	else if(currentCard.getTarget() == Constants.targetEveryoneElse)
                	{
                		showfirst = true;
                		
                		if(currentCard.getName() == Constants.SizeMattersName)
                		{
                			sizeResult = rollDice();
                		}
                		
                		removeCard(selectCardIndex);
                		
                		for(int i=0; i<playerOrder.size(); i++)
                		{
                			if(i != myIndex)
                			{
                				if(!((Player)playerOrder.get(i)).getPlayerState().contains(Constants.NegationName))
                    			{
                					if(showfirst)
                						useSpell(currentCard, (Player)playerOrder.get(i));
                					else useSpell(currentCard, (Player)playerOrder.get(i), false);
                    			}
                			}
                		}
                		
                		showfirst = true;
                		sizeResult = 0;
                		clearActionImage();
                	}
                	else if(currentCard.getTarget() == Constants.targetEveryone)
                	{
                		showfirst = true;
                		
                		removeCard(selectCardIndex);
                		for(int i=0; i<playerOrder.size(); i++)
                		{
                			if(!((Player)playerOrder.get(i)).getPlayerState().contains(Constants.NegationName))
                			{
                				if(showfirst)
            						useSpell(currentCard, (Player)playerOrder.get(i));
            					else useSpell(currentCard, (Player)playerOrder.get(i), false);
                			}
                		}
                		
                		showfirst = true;
                		resetCards();
                		setCardImages();
                		clearActionImage();
                	}
                	else if(currentCard.getTarget() == Constants.targetTeam)
                	{
                		boolean targetSelf = true;
                		for(int i=0; i<playerOrder.size(); i++)
                		{
                			Player target = (Player)playerOrder.get(i);
                			
                			if(target.getSelected() && target.getTeam() == me.getTeam())
                			{
                				update(currentCard, me, target);
                				target.setSelected(false);
                				targetSelf = false;
                				break;
                			}
                		}
                		
                		if(targetSelf)
                		{
            				update(currentCard, me, me);
                		}
                	}
            	}
            	
            }
        });
    	
    	cancelButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) { 
            	if(thread.mMode != thread.STATE_RUNNING)
            	{
            		return;
            	}
            	
            	if(currentPlayer != myIndex)
            	{
            		return;
            	}
            	
            	else{
            		if(currentPhase == Constants.playPhase)
            		{
            			for(int i=0; i<playerOrder.size(); i++)
                		{
                			Player target = (Player)playerOrder.get(i);
                			
                			if(target.getSelected())
                			{
                				target.setSelected(false);
                				updatePlayerImage(target);
                				break;
                			}
                		}
            		}
            		changePhase();
            	}
            	
            }
        });
    	
    	skill1.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	if(thread.mMode != thread.STATE_RUNNING)
            	{
            		return;
            	}
            	
            	if(me.getSkill1() == Constants.skill13)
            	{
            		if(selectCardIndex != -1)
            		{
            			Card currentCard = (Card)inHands.get(selectCardIndex);
            			if(currentCard.getName() == Constants.ShieldName)
            			{
            				currentCard.setName(Constants.SwordName);
            				currentCard.setType(Constants.typeWeapon);
            				currentCard.setTarget(Constants.targetEnemy);
            				currentCard.setDistance(1);
            				
            				resetCards();
            				setCardImages();
            			}
            			else
            			{
            				battleText = "Can only use Shield card";
            			}
            			
            		}
            	}//end if
            	
            	if(me.getSkill1() == Constants.skill9)
            	{
            		if(skill1Used)
            		{
            			battleText = "Can only use once per turn!";
            			return;
            		}
            		int sum = inHands.size();
            		inHands = new Vector();
            		for(int i = 0; i < sum; i++)
            		{
            			inHands.add(deck.getNextCard());
            		}
            		resetCards();
    				setCardImages();
            		me.setInHands(inHands);
            		skill1Used = true;
            	}//end if
            	
            	if(me.getSkill1() == Constants.skill11)
            	{
            		if(selectCardIndex != -1)
            		{
            			Card currentCard = (Card)inHands.get(selectCardIndex);
            			if(currentCard.getType() == Constants.typeWeapon)
            			{
            				me.getPlayerState().add(Constants.skill11);
            				inHands.remove(selectCardIndex);
                			setCardImages();
            			}
            			else
            			{
            				battleText = "Can only use weapon card";
            			}
            		}
            	}//end if
            	
            	if(me.getSkill1() == Constants.skill17)
            	{
            		if(skill1Used)
            		{
            			battleText = "Can only use once per turn!";
            			return;
            		}
            		
            		Player target = me;
            		
            		for(int i = 0; i < playerOrder.size(); i ++)
            		{
            			Player p = (Player)playerOrder.get(i);
            			if(p.getSelected() && p.getTeam() == me.getTeam())
            			{
            				target = p;
            			}
            		}
            		
            		if(target.getCurrentHP() >= 5)
            		{
            			battleText = "Target already at full hp!";
            			return;
            		}
            		else if(selectCardIndex != -1){
            			Card currentCard = (Card)inHands.get(selectCardIndex);
            			if(currentCard.getName() == Constants.ShieldName)
            			{
            				target.setCurrentHP(target.getCurrentHP() + 1);
            			}
            			else
            			{
            				battleText = "Can only use Shield card";
            			}
            			inHands.remove(selectCardIndex);
            			setCardImages();
            			skill1Used = true;
            		}
            	}//end if
            	
            	if(me.getSkill1() == Constants.skill21)
            	{
            		if(skill1Used)
            		{
            			battleText = "Can only use once per turn!";
            			return;
            		}
            		
            		for(int i = 0; i < playerOrder.size(); i ++)
            		{
            			Player p = (Player)playerOrder.get(i);
            			if(p.getSelected() && p.getTeam() == me.getTeam())
            			{
            				if(p.getCurrentHP() >= 5)
            				{
            					battleText = "Target has full hp!";
            					return;
            				}
            				else
            				{
            					me.setCurrentHP(me.getCurrentHP() - 1);
            					skullTarget = me;
            					updateSkullImage();
            					p.setCurrentHP(p.getCurrentHP() + 1);
            					inHands.add(deck.getNextCard());
            					setCardImages();
            					checkEnd();
            					skill1Used = true;
            					return;
            				}
            			}
            		}
            	}//end if
            	
            	if(me.getSkill1() == Constants.skill23)
            	{
            		if(skill1Used)
            		{
            			battleText = "Can only use once per turn!";
            			return;
            		}
            		
            		Player p1 = null;
            		
            		for(int i = 0; i < playerOrder.size(); i ++)
            		{
            			Player p = (Player)playerOrder.get(i);
            			if(p.getSelected())
            			{
            				p1 = p;
            			}
            		}

    				int roll = rollDice();
    				diceResult = roll;
					actioner= me;
		    		updateDiceImage();
		    		
    				if(roll == 6)
    				{
    					p1.setCurrentHP(p1.getCurrentHP() - 1);
    					skullTarget = p1;
    					updateSkullImage();
    					me.setCurrentHP(me.getCurrentHP() - 1);
    					skullTarget = me;
    					updateSkullImage();
        				checkEnd();
        				skill1Used = true;
    				}   		
            	}//end if
            }
    	});
    	
    	skill2.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	if(thread.mMode != thread.STATE_RUNNING)
            	{
            		return;
            	}
            	
            	if(me.getSkill2() == Constants.skill22)
            	{
            		if(selectCardIndex != -1)
            		{
            			Card currentCard = (Card)inHands.get(selectCardIndex);
            			if(currentCard.getName() == Constants.SwordName)
            			{
            				currentCard.setName(Constants.ShieldName);
            				currentCard.setType(Constants.typeShield);
            				currentCard.setTarget(Constants.targetNone);
            				
            				resetCards();
            				setCardImages();
            			}
            			else
            			{
            				battleText = "Can only use sword card";
            			}
            		}
            	}//end if
            	
            	if(me.getSkill2() == Constants.skill8)
            	{
            		if(skill2Used)
            		{
            			battleText = "Can only use once per turn!";
            			return;
            		}
            		
            		if(selectCardIndex != -1)
            		{
            			Card currentCard = (Card)inHands.get(selectCardIndex);
            			
            			if(currentCard.getType() != Constants.typeShield)
            			{
            				battleText = "Can only use shield card!";
            				return;
            			}
            			for(int i=0; i<playerOrder.size(); i++)
                		{
                			Player target = (Player)playerOrder.get(i);
                			
                			if(target.getSelected() && target.getTeam() != me.getTeam())
                			{
                				target.getPlayerState().add(Constants.skipDraw);
                				target.setSelected(false);
                				
                				inHands.remove(selectCardIndex);
                				setCardImages();
                				
                    			skill2Used = true;
                    			break;
                			}
                		}
            		}
            	}//end if
            	
            	if(me.getSkill2() == Constants.skill14)
            	{
            		if(skill2Used)
            		{
            			battleText = "Can only use once per turn!";
            			return;
            		}
            		
            		for(int i=0; i<playerOrder.size() && selectCardIndex != -1; i++)
            		{
            			Player target = (Player)playerOrder.get(i);
            			
            			if(target.getSelected())
            			{
            				if(target.getPlayerState().size() == 0)
            				{
            					battleText = "This player has no status";
            					return;
            				}
            				else{
    		            		inHands.remove(selectCardIndex);
    		        			target.getPlayerState().remove(0);
    		        			target.setStatusImages();
    		        			skill2Used = true;
    		        			return;
            				}
            			}
            		}
            	}//end if
            	
            	if(me.getSkill2() == Constants.skill18)
            	{
            		if(skill2Used)
            		{
            			battleText = "Can only use once per turn!";
            			return;
            		}
            		
            		for(int i=0; i<playerOrder.size(); i++)
            		{
            			Player target = (Player)playerOrder.get(i);
            			if(target.getSelected() && target.getGender() == Constants.male)
            			{
            				Vector tmpInHands = target.getInHands();
            				for(int j = 0; j < tmpInHands.size(); j++)
            				{
            					Card tmpCard = (Card)tmpInHands.get(j);
            					if(tmpCard.getName() == Constants.ShieldName)
            					{
            						int roll = rollDice();
            						/* diceResult = roll;
            						actioner= me;
            			    		updateDiceImage();*/
            			    		
            						if(roll % 2 ==0)
            						{
            							inHands.add(tmpCard);
            							tmpInHands.remove(j);
            							setCardImages();
            							
            							skill2Used = true;
            							return;
            						}
            					}
            				}
            			}//end if
            			else
            			{
            				battleText = "Can only use on male character!";
            			}
            		}//end for
            	}//end if
            	
            	if(me.getSkill2() == Constants.skill26)
            	{
            		if(skill2Used)
            		{
            			battleText = "Can only use once per turn!";
            			return;
            		}
            		
            		if(selectCardIndex != -1)
            		{
            			Card currentCard = (Card)inHands.get(selectCardIndex);
            			
            			if(currentCard.getType() != Constants.typeShield)
            			{
            				battleText = "Can only use shield card!";
            				return;
            			}
            			for(int i=0; i<playerOrder.size(); i++)
                		{
                			Player target = (Player)playerOrder.get(i);
                			
                			if(target.getSelected() && target.getTeam() != me.getTeam())
                			{
                				target.getPlayerState().add(Constants.skipPlay);
                				target.setSelected(false);
                				
                				inHands.remove(selectCardIndex);
                				setCardImages();
                				
                    			skill2Used = true;
                    			break;
                			}
                		}
            		}
            	}//end if
            }
    	});
    }
    
    //remove the card from player's hand and reset the images shown
    private void removeCard(int index)
    {
		inHands.remove(index);
		selectCardIndex = -1;
		setCardImages();
    }
    
    private void update(Card card, Player from, Player target)
    {
    	
    	if(card.getType() == Constants.typeWeapon)
    	{
    		if(hasAttacked)
    		{
    			battleText = "you have already used weapon card this turn!";
    		}
    		else {
    			if(calcDist(from, target) > card.getDistance())
    			{
    				battleText = "You can not reach this target using this weapon card!";
    			}
    			else{
    				removeCard(selectCardIndex);
        			useWeapon(card.getName(), from, target, true);
    			}
    		}
    	}
    	
    	else if(card.getType() == Constants.typePotion)
    	{
        	actioner = from;
        	actioncard = card.getName();
        	
    		usePotion(target);
    	}
    	
    	else if(card.getType() == Constants.typeSpell)
    	{
    	    if(card.getName() == Constants.CurseName || card.getName() == Constants.SpiritName || card.getName() == Constants.SilenceName)
    	    {
    	    	if(target.getSkill2() == Constants.skill4)
    	    	{
    	    		battleText = "The target is now immune to this spell!";
    	    		return;
    	    	}
    	    }
    	    
    		if(!target.getPlayerState().contains(Constants.NegationName))
    		{
	    		removeCard(selectCardIndex);
	    		useSpell(card, target);
    		}
    		else{
    			battleText = "The target is now immune to spell!";
    		}
    	}
    }
    
    private void useSpell(Card card, Player target)
    {
    	useSpell(card, target, true);
    	showfirst = false;
    }
    
    private void useSpell(Card card, Player target, Boolean show)
    {
    	if(show)
    	{
	    	actioncard = card.getName();
	    	updateActionImage();
	    	
	    	if(sizeResult != 0)
	    	{
	    		diceResult = sizeResult;
	    		updateDiceImage();
	    	}
    	}
    	
    	Vector tmpInHands = target.getInHands();
    	int cardIndex = -1;
    	Player from = (Player)playerOrder.get(currentPlayer);
    	
    	if(from.getSkill1() == Constants.skill3 && show)
    	{
    		if(card.getName() == Constants.FateName || card.getName() == Constants.PoisonName || card.getName() == Constants.RouletteName || card.getName() == Constants.WheelName || card.getName() == Constants.SizeMattersName)
    		{
    			int result = rollDice();
    			diceResult = result;
				actioner= from;
	    		updateDiceImage();
	    		
    			if((result % 2) == 0)
    			{
    				from.setCurrentHP(from.getCurrentHP() + 1);
    				if(from.getCurrentHP() >  Constants.InitialHP)
    					from.setCurrentHP(Constants.InitialHP);
    			}
    		}
    	}
    	
    	if(card.getName() == Constants.AmageddonName)
    	{  		
    		for(int i = 0; i < tmpInHands.size(); i++)
        	{
        		if(((Card)tmpInHands.get(i)).getType() == Constants.typeShield)
        		{
        			cardIndex = i;
        		}
        	}
        	
        	if(cardIndex != -1)
        	{
        		actioner = target;
            	actioncard = Constants.ShieldName;
            	updateActionImage();
    	    	tmpInHands.remove(cardIndex);
        	}
        	else 
        	{
        		target.setCurrentHP(target.getCurrentHP() - 1);
        		skullTarget = target;
				updateSkullImage();
        		if(target.getTeam() != ((Player)playerOrder.get(currentPlayer)).getTeam())
    			{
    				damageDealt += 1;
    			}
        		checkEnd();
        	}
    	}
    	else if(card.getName() == Constants.InvasionName)
    	{	
    		for(int i = 0; i < tmpInHands.size(); i++)
        	{
        		if(((Card)tmpInHands.get(i)).getType() == Constants.typeWeapon)
        		{
        			cardIndex = i;
        		}
        	}
        	
        	if(cardIndex != -1)
        	{
        		actioner = target;
            	actioncard = ((Card)tmpInHands.get(cardIndex)).getName();
            	updateActionImage();
    	    	tmpInHands.remove(cardIndex);
        	}
        	else 
        	{
        		target.setCurrentHP(target.getCurrentHP() - 1);
        		skullTarget = target;
				updateSkullImage();
        		if(target.getTeam() != ((Player)playerOrder.get(currentPlayer)).getTeam())
    			{
    				damageDealt += 1;
    			}
        		checkEnd();
        	}
    	}
    	
    	else if(card.getName() == Constants.RevelationName)
    	{
    		battleText = target.getpClass() + " has: ";
    		Vector tmpInhands = target.getInHands();
    		for (int i = 0; i < tmpInhands.size(); i++)
    		{
    			battleText = battleText + ((Card)tmpInhands.get(i)).getName() + "  ";
    		}
    		
    	}
    	
    	else if(card.getName() == Constants.FateName)
    	{
    		Vector state = target.getPlayerState();
    		state.add(Constants.FateName);
    		target.setPlayerState(state);
    	}
    	
    	else if(card.getName() == Constants.PoisonName)
    	{
    		Vector state = target.getPlayerState();
    		state.add(Constants.PoisonName);
    		target.setPoisonRound(Constants.PoisonRound);
    		target.setPlayerState(state);
    	}
    	
    	else if(card.getName() == Constants.GenerosityName)
    	{
    		tmpInHands.add(deck.getNextCard());
    	}
    	
    	else if(card.getName() == Constants.TruceName)
    	{
    		if(target.getCurrentHP() < 5)
    		{
    			target.setCurrentHP(target.getCurrentHP() + 1);
    			updateHPImage();
    		}
    	}
    	
    	else if(card.getName() == Constants.SilenceName)
    	{
    		Vector state = target.getPlayerState();
    		state.add(Constants.SilenceName);
    		target.setPlayerState(state);
    	}
    	
    	else if(card.getName() == Constants.SpiritName)
    	{
    		Vector state = target.getPlayerState();
    		state.add(Constants.SpiritName);
    		target.setPlayerState(state);
    	}
    	
    	else if(card.getName() == Constants.HexName)
    	{
    		Vector state = target.getPlayerState();
    		state.add(Constants.HexName);
    		target.setPlayerState(state);
    	}
    	
    	else if(card.getName() == Constants.NegationName)
    	{
    		Vector state = target.getPlayerState();
    		state.add(Constants.NegationName);
    		target.setNegationCount(1);
    		target.setPlayerState(state);
    	}
    	
    	else if(card.getName() == Constants.CurseName)
    	{
    		if(tmpInHands.size() > 0)
    		{
    			int cardToDrop = (int)(tmpInHands.size() * Math.random());
    			tmpInHands.remove(cardToDrop);
    			target.setInHands(tmpInHands);
    			
    			if(target.getName() == me.getName())
    			{
    				setCardImages();
    			}
    		}
    		else{
    			battleText = "The target has no cards in hand!";
    		}
    	}
    	
    	else if(card.getName() == Constants.DoubleEdgeName)
    	{
    		Player p = (Player)playerOrder.get(currentPlayer);
    		if(target.getSkill2() == Constants.skill6)
    		{
    			int result = rollDice();
    			diceResult = result;
				actioner= p;
	    		updateDiceImage();
	    		
    			if(result % 2 != 0)
    			{
    				target.setCurrentHP(target.getCurrentHP() - 1);
    				skullTarget = target;
					updateSkullImage();
            		damageDealt += 1;
    			}
    		}
    		else{
    			target.setCurrentHP(target.getCurrentHP() - 1);
    			skullTarget = target;
				updateSkullImage();
        		damageDealt += 1;
    		}
    		
    		if(p.getSkill2() == Constants.skill6)
    		{
    			int result = rollDice();
    			diceResult = result;
				actioner= p;
	    		updateDiceImage();
	    		
    			if(result % 2 != 0)
    			{
    				p.setCurrentHP(p.getCurrentHP() - 1);
    				skullTarget = p;
					updateSkullImage();
    			}
    		}
    		else{
    			p.setCurrentHP(p.getCurrentHP() - 1);
    			skullTarget = p;
				updateSkullImage();
    		}
    		
    		checkEnd();
    	}
    	
    	else if(card.getName() == Constants.RouletteName)
    	{
    		int result = rollDice();
    		diceResult = result;
			actioner= target;
    		updateDiceImage();
    		
    		if(result == 1)
    		{
    			if(target.getSkill2() == Constants.skill6) 
    			{
    				int roll = rollDice();
    				if(roll % 2 != 0)
        			{
        				target.setCurrentHP(target.getCurrentHP() - 1);
        				skullTarget = target;
    					updateSkullImage();
            			if(target.getTeam() != ((Player)playerOrder.get(currentPlayer)).getTeam())
            			{
            				damageDealt += 1;
            			}
        			}
    			}
    			else{
    				target.setCurrentHP(target.getCurrentHP() - 1);
    				skullTarget = target;
					updateSkullImage();
        			if(target.getTeam() != ((Player)playerOrder.get(currentPlayer)).getTeam())
        			{
        				damageDealt += 1;
        			}
    			}
    			checkEnd();
    		}
    	}
    	
    	else if(card.getName() == Constants.SizeMattersName)
    	{
    		int result = rollDice();
    		diceResult = result;
			actioner= target;
    		updateDiceImage();
    		
    		if(result < sizeResult)
    		{
    			if(target.getSkill2() == Constants.skill6) 
    			{
    				int roll = rollDice();
    				diceResult = result;
    				actioner= target;
    	    		updateDiceImage();
    	    		
    				if(roll % 2 != 0)
        			{
        				target.setCurrentHP(target.getCurrentHP() - 1);
        				skullTarget = target;
    					updateSkullImage();
            			if(target.getTeam() != ((Player)playerOrder.get(currentPlayer)).getTeam())
            			{
            				damageDealt += 1;
            			}
        			}
    			}
    			else{
    				target.setCurrentHP(target.getCurrentHP() - 1);
    				skullTarget = target;
					updateSkullImage();
        			if(target.getTeam() != ((Player)playerOrder.get(currentPlayer)).getTeam())
        			{
        				damageDealt += 1;
        			}
    			}
    			checkEnd();
    		}
    	}
    	
    	else if(card.getName() == Constants.ShallowName)
    	{
    		Vector state = target.getPlayerState();
    		state.add(Constants.ShallowName);
    		target.setShallowCount(3);
    		target.setPlayerState(state);
    	}
    	
    	else if(card.getName() == Constants.WheelName)
    	{
    		int result = rollDice();
    		diceResult = result;
			actioner= target;
    		updateDiceImage();
    		
    		if(result == 1)
    		{
    			if(tmpInHands.size() > 1)
    			{
    				int random = (int)(tmpInHands.size() * Math.random());
    				tmpInHands.remove(random);
    			}
    		}
    		else if(result == 2)
    		{
    			tmpInHands.add(deck.getNextCard());
    		}
    		else if(result == 3)
    		{
    			tmpInHands.add(deck.getNextCard());
    			tmpInHands.add(deck.getNextCard());
    		}
    		else if(result == 4)
    		{
    			target.setCurrentHP(target.getCurrentHP() - 1);
    			skullTarget = target;
				updateSkullImage();
    			checkEnd();
    		}
    		else if(result == 5)
    		{
    			target.setCurrentHP(target.getCurrentHP() + 1);
    		}
    		else if(result == 6)
    		{
    			target.setCurrentHP(target.getCurrentHP() + 2);
    		}
    		target.setInHands(tmpInHands);
    		if(target.getCurrentHP() > Constants.InitialHP)
    		{
    			target.setCurrentHP(Constants.InitialHP);
    		}
    		
    		if(target.getName() == me.getName())
			{
				setCardImages();
			}
    	}
    }
    
    //the game logic that involves using a potion card
    private void usePotion(Player target)
    {
    	if(target.getCurrentHP() < Constants.InitialHP)
    	{
        	updateActionImage();
        	
    		target.setCurrentHP(target.getCurrentHP() + 1);
    		updateHPImage();
    		
    		removeCard(selectCardIndex);
    	}
    	else 
    	{
    		battleText = "You are already at full hp!";
    	}
    }
    
    
    //the game logic that involves using a weapon card
    private void useWeapon(String weapon, Player from, Player target, boolean canRetaliate)
    {
    	actioner = from;
    	actioncard = weapon;
    	updateActionImage();
    	
    	Vector tmpInHands = target.getInHands();
    	int shieldIndex = -1;
    	int weaponIndex = -1;
    	
    	if(from.getSkill2() == Constants.skill24 && assassinCount > 0)
    	{
    		assassinCount--;
    	}
    	else{
    		hasAttacked = true;
    	}
    	
    	if(from.getName() == Constants.skill20)
    	{
    		canRetaliate = false;
    	}
    	
    	if(from.getSkill2() == Constants.skill28 && (target.getCurrentHP() - from.getCurrentHP()) > 1)
    	{
    		target.takeDamage(1);
    		return;
    	}
    	
    	for(int i = 0; i < tmpInHands.size(); i++)
    	{
    		if(((Card)tmpInHands.get(i)).getType() == Constants.typeShield)
    		{
    			shieldIndex = i;
    		}
    	}
    	
    	if(shieldIndex != -1)
    	{
    		actioner = target;
        	actioncard = Constants.ShieldName;
        	updateActionImage();
	    	tmpInHands.remove(shieldIndex);
	    	
	    	if(myIndex == currentPlayer)
	    	{
	    		setCardImages();
	    	}
    	}
    	else 
    	{
    		int damage = 0;
    		if(weapon == Constants.BowName && from.getSkill1() == Constants.skill19)
    		{
    			damage = target.takeDamage(2);
    		}
    		else if(!canRetaliate && from.getSkill1() == Constants.skill27)
    		{
    			damage = target.takeDamage(2);
    		}
    		else if(from.getPlayerState().contains(Constants.skill11))
    		{
    			damage = target.takeDamage(2);
    			from.getPlayerState().remove(Constants.skill11);
    		}
    		else{
    			damage = target.takeDamage(1);
    		}
    		damageDealt += damage;
    		if (damage > 0 && from.getSkill1() == Constants.skill5)
    		{
    			if(tmpInHands.size() > 0)
        		{
        			int cardToDrop = (int)(tmpInHands.size() * Math.random());
        			tmpInHands.remove(cardToDrop);
        			target.setInHands(tmpInHands);
        			//setCardImages();
        		}
    		}
    		if(damage > 0 && target.getSkill2() == Constants.skill12 && from.getGender() == Constants.male)
			{
    			int result = rollDice();
    			diceResult = result;
				actioner= target;
	    		updateDiceImage();
	    		
    			if(result == 1 || result == 6)
    			{
    				from.setCurrentHP(from.getCurrentHP() - 1);
    				skullTarget = from;
					updateSkullImage();
    			}
				checkEnd();
			}
    		checkEnd();
    	}
    	
    	if(canRetaliate)
    	{
	    	for(int i = 0; i < tmpInHands.size(); i++)
	    	{
	    		if(((Card)tmpInHands.get(i)).getName() == weapon)
	    		{
	    			weaponIndex = i;
	    		}
	    	}
    	}
    	
    	if(weaponIndex != -1)
    	{
	    	tmpInHands.remove(weaponIndex);
	    	useWeapon(weapon, target, from, false);
    	}
    	
    	target.setInHands(tmpInHands);
    	target.removeState();
    }
    
    //progress the game into the next phase
    private void changePhase()
    {
    	if(currentPhase == Constants.drawingPhase)
    	{
    		currentPhase = Constants.playPhase;
    		battleText = ((Player)playerOrder.get(currentPlayer)).getpClass() + " " + mRes.getString(R.string.playPhase);
    		
    		checkPoison();
    		updateCardNumberImage();
    	}
    	else if(currentPhase == Constants.playPhase)
    	{
    		clearActionImage();
    		resetCards();
    		setCardImages();
    		
    		battleText = " ";
    		if(currentPlayer == myIndex)
    		{
	    		resetCards();
	    		
	    		if(inHands.size() > Constants.AfterDiscardNumber)
	    		{
	    			currentPhase = Constants.discardPhase;
	    			battleText = mRes.getString(R.string.discardPhase1) + " " + String.valueOf(inHands.size() - Constants.AfterDiscardNumber) + " " + mRes.getString(R.string.discardPhase2);
	    		}
	    		
	    		else {
	    			nextPlayer();
	    			battleText = ((Player)playerOrder.get(currentPlayer)).getpClass() + " " + mRes.getString(R.string.drawPhase);
	    			currentPhase = Constants.drawingPhase;
	    		}
    		}
    		else
    		{
    			currentPhase = Constants.discardPhase;
    			battleText = ((Player)playerOrder.get(currentPlayer)).getpClass() + " " + mRes.getString(R.string.discardPhase);
    		}
    	}
    	else if(currentPhase == Constants.discardPhase)
    	{
    		battleText = " ";
    		if(currentPlayer == myIndex)
    		{
	    		if(inHands.size() > Constants.AfterDiscardNumber)
	    		{
	    			int handSize = inHands.size();
	    			for (int i = 0; i < handSize - Constants.AfterDiscardNumber; i++ )
	    			{
	    				inHands.remove(0);
	    			}
	    		}
    		
	    		resetCards();
	    		setCardImages();
    		}
    		
    		nextPlayer();
    		hasAttacked = false;
    		
    		battleText = ((Player)playerOrder.get(currentPlayer)).getpClass() + " " + mRes.getString(R.string.drawPhase);
    		currentPhase = Constants.drawingPhase;
    	}
    }
    
    private void nextPlayer()
    {
    	
    	Player p1 = (Player)playerOrder.get(currentPlayer);
    	p1.clearStateAfter();
    	
    	//clear all the selected target
    	for(int j =0; j<playerOrder.size(); j++)
		{
			Player target = (Player)playerOrder.get(j);
			if (target.getSelected())
			{
				target.setSelected(false);
			}
		}
    	
    	if(p1.getSkill1() == Constants.skill25)
    	{
    		for(int i = 0; i < playerOrder.size(); i++)
    		{
    			if(((Player)playerOrder.get(i)).getGender() == Constants.female)
    			{
    				p1.getInHands().add(deck.getNextCard());
    				resetCards();
    	    		setCardImages();
    	    		break;
    			}
    		}
    	}
    	
    	if(damageDealt > 1 && p1.getSkill1() == Constants.skill7)
    	{
    		if(p1.getCurrentHP() < 5)
    		{
    			p1.setCurrentHP(p1.getCurrentHP() + 1);
    		}
    	}
    	damageDealt = 0;
    	assassinCount = 1;
    	
    	if(p1.getSkill2() == Constants.skill10 && p1.getInHands().size() == 0)
    	{
    		p1.getInHands().add(deck.getNextCard());
    		resetCards();
    		setCardImages();
    	}
    	
    	currentPlayer += 1;
    	if(currentPlayer == playerOrder.size())
    	{
    		currentPlayer = 0;
    	}
    	
    	Player p2 = (Player)playerOrder.get(currentPlayer);
    	p2.clearStateBefore();
    	
    	retaliateFlag = null;
    }
    
    //return all the cards to the initial position
    private void resetCards()
    {
    	selectCardIndex = -1;
    	for (int i = 0; i < inHands.size(); i++)
    	{
    		Card tmpCard = (Card)inHands.get(i);
			tmpCard.setSelected(false);
			inHands.set(i, tmpCard);
    	}
    }
    
    //TODO The AIs will need improvement later
    private void playAI()
    {
    	Player current = (Player)playerOrder.get(currentPlayer);
    	Vector tmpHand = current.getInHands();

    	hasAttacked = false;
    	Vector weaponNumber = new Vector();
    	Vector shieldNumber = new Vector();
		for(int k = 0; k < tmpHand.size(); k ++)
		{
			Card tmpc = (Card) tmpHand.get(k);
			if(tmpc.getType() == Constants.typeWeapon)
			{
				weaponNumber.add(k);
			}
			else if(tmpc.getType() == Constants.typeShield)
			{
				shieldNumber.add(k);
			}
		}
		
    	if(current.getSkill1() == Constants.skill9)
    	{
    		
    	}
    	else if(current.getSkill1() == Constants.skill11)
    	{
    		if(weaponNumber.size() > 1)
    		{
    			current.getPlayerState().add(Constants.skill11);
    			tmpHand.remove(weaponNumber.get(0));
    		}
    	}
    	else if(current.getSkill1() == Constants.skill13)
    	{
    		if(weaponNumber.size() == 0 && shieldNumber.size() > 1)
    		{
    			((Card)tmpHand.get((Integer)shieldNumber.get(0))).setName(Constants.SwordName);
    			((Card)tmpHand.get((Integer)shieldNumber.get(0))).setType(Constants.typeWeapon);
    			((Card)tmpHand.get((Integer)shieldNumber.get(0))).setTarget(Constants.targetEnemy);
    			((Card)tmpHand.get((Integer)shieldNumber.get(0))).setDistance(1);
    		}
    	}
    	else if(current.getSkill1() == Constants.skill17)
    	{
    		int lowest = findLowestHP(current);
			
    		if(shieldNumber.size() > 0 && ((Player)playerOrder.get(lowest)).getCurrentHP() < 5)
    		{
    			battleText = current.getpClass() + " used healing on " + ((Player)playerOrder.get(lowest)).getpClass();
    			((Player)playerOrder.get(lowest)).setCurrentHP(((Player)playerOrder.get(lowest)).getCurrentHP() + 1);
    			tmpHand.remove(shieldNumber.get(0));
    			updateHPImage();
    		}
    	}
    	else if(current.getSkill1() == Constants.skill21)
    	{
    		int lowest = findLowestHP(current);
    		if (lowest != currentPlayer && current.getCurrentHP() > 3)
    		{
    			battleText = current.getpClass() + " used sacrifice on " + ((Player)playerOrder.get(lowest)).getpClass();
    			current.setCurrentHP(current.getCurrentHP() - 1);
    			skullTarget = current;
				updateSkullImage();
    			((Player)playerOrder.get(lowest)).setCurrentHP(((Player)playerOrder.get(lowest)).getCurrentHP() + 1);
    			updateHPImage();
    		}
    	}
    	else if(current.getSkill1() == Constants.skill23)
    	{

    	}
    	
    	if(current.getSkill2() == Constants.skill8)
    	{
    		if(shieldNumber.size() > 1)
    		{
    			for(int i=0; i<playerOrder.size(); i++)
        		{
        			Player target = (Player)playerOrder.get(i);
        			
        			if(target.getTeam() != current.getTeam())
        			{
        				target.getPlayerState().add(Constants.skipDraw);
        				
        				tmpHand.remove(shieldNumber.get(0));
            			break;
        			}
        		}
    		}
    	}
    	else if(current.getSkill2() == Constants.skill14)
    	{
    		
    	}
    	else if(current.getSkill2() == Constants.skill18)
    	{
    		for(int i=0; i<playerOrder.size(); i++)
    		{
    			Player target = (Player)playerOrder.get(i);
    			if(target.getGender() == Constants.male && target.getTeam() != current.getTeam())
    			{
    				Vector tmpInHands = target.getInHands();
    				for(int j = 0; j < tmpInHands.size(); j++)
    				{
    					Card tmpCard = (Card)tmpInHands.get(j);
    					if(tmpCard.getName() == Constants.ShieldName)
    					{
    						int roll = rollDice();
    			    		
    						if(roll % 2 ==0)
    						{
    							battleText = current.getpClass() + " got a shield card from " + target.getpClass();
    							tmpHand.add(tmpCard);
    							tmpInHands.remove(j);
    							
    							return;
    						}
    					}
    				}
    			}//end if
    		}//end for
    	}
    	else if(current.getSkill2() == Constants.skill22)
    	{
    		if(weaponNumber.size() > 1 && shieldNumber.size() == 0)
    		{
    			((Card)tmpHand.get((Integer)weaponNumber.get(0))).setName(Constants.ShieldName);
    			((Card)tmpHand.get((Integer)weaponNumber.get(0))).setType(Constants.typeShield);
    			((Card)tmpHand.get((Integer)weaponNumber.get(0))).setTarget(Constants.targetNone);
    		}
    	}
    	else if(current.getSkill2() == Constants.skill26)
    	{
    		if(shieldNumber.size() > 1)
    		{
    			for(int i=0; i<playerOrder.size(); i++)
        		{
        			Player target = (Player)playerOrder.get(i);
        			
        			if(target.getTeam() != me.getTeam())
        			{
        				target.getPlayerState().add(Constants.skipPlay);				
        				tmpHand.remove(shieldNumber.get(0));

            			break;
        			}
        		}
    		}
    	}

    	for(int i = 0; i < tmpHand.size(); i++)
    	{
    		actioner = current;
    		
    		if(current.getCurrentHP() <= 0)
    		{
    			return;
    		}
    		Card c = (Card) tmpHand.get(i);
    		if(c.getType() == Constants.typePotion)
    		{
    			int lowest = findLowestHP(current);
    			
    			if (((Player)playerOrder.get(lowest)).getCurrentHP() < Constants.InitialHP)
    			{
    				actioncard = c.getName();
    				updateActionImage();
  
    				((Player)playerOrder.get(lowest)).setCurrentHP(((Player)playerOrder.get(lowest)).getCurrentHP() + 1);  
    				updateHPImage();
    				tmpHand.remove(i);
    				i--;
    			}
    		}
    		else if(c.getType() == Constants.typeSpell)
    		{
    			if(!current.getPlayerState().contains(Constants.SilenceName))
    			{
    				if(c.getTarget() == Constants.targetEnemy)
                	{
                		for(int j=0; j<playerOrder.size(); j++)
                		{
                			Player target = (Player)playerOrder.get(j);
                			
                			if(target.getTeam() != current.getTeam() && !target.getPlayerState().contains(Constants.NegationName))
                			{
                				if(c.getName() == Constants.CurseName && target.getInHands().size() == 0)
                				{
                					
                				}
                				else if(c.getName() == Constants.DoubleEdgeName && current.getCurrentHP() < target.getCurrentHP())
                				{
                					
                				}
                				else{
	                				useSpell(c, target);
	                				
	                				tmpHand.remove(i);
	                				i--;
	                				break;
                				}
                			}
                		}
                	}
                	else if(c.getTarget() == Constants.targetSelf)
                	{
                		if(!current.getPlayerState().contains(Constants.NegationName))
                		{
	                		useSpell(c, current);
	        				tmpHand.remove(i);
	        				i--;
                		}
                	}
                	else if(c.getTarget() == Constants.targetEveryoneElse)
                	{
                		showfirst = true;
                		
                		if(c.getName() == Constants.SizeMattersName)
                		{
                			sizeResult = rollDice();
                		}
                		
                		for(int j=0; j<playerOrder.size(); j++)
                		{
                			actioner = current;
                			
                			if(j != currentPlayer && !((Player)playerOrder.get(j)).getPlayerState().contains(Constants.NegationName))
                			{
                				if(showfirst)
                					useSpell(c, (Player)playerOrder.get(j));
                				else useSpell(c, (Player)playerOrder.get(j), false);
                			}
                		}
        				
                		showfirst = true;
                		sizeResult = 0;
                		
        				tmpHand.remove(i);
        				i--;
        				clearActionImage();
                	}
                	else if(c.getTarget() == Constants.targetEveryone)
                	{
                		showfirst = true;
                		
                		for(int j=0; j<playerOrder.size(); j++)
                		{
                			actioner = current;
                			
                			if(!((Player)playerOrder.get(j)).getPlayerState().contains(Constants.NegationName))
                			{
                				if(showfirst)
                					useSpell(c, (Player)playerOrder.get(j));
                				else useSpell(c, (Player)playerOrder.get(j), false);
                			}
                		}
                		
                		showfirst = true;
                		resetCards();
                		setCardImages();
        				
        				tmpHand.remove(i);
        				i--;
        				clearActionImage();
                	}
                	else if(c.getTarget() == Constants.targetTeam)
                	{
                		if(!current.getPlayerState().contains(Constants.NegationName))
                		{
	                		useSpell(c, current);		
	        				tmpHand.remove(i);
	        				i--;
                		}
                	}

    			}
    		}
	    	
    	}//for loop
    	
    	for(int i = 0; i < tmpHand.size(); i++)
    	{
    		actioner = current;
    		if(current.getCurrentHP() <= 0)
    		{
    			return;
    		}
    		Card c = (Card) tmpHand.get(i);

    		if(!current.getPlayerState().contains(Constants.SpiritName))
			{
	    		if(c.getType() == Constants.typeWeapon)
	    		{
	    			for(int j =0; j<playerOrder.size(); j++)
	        		{
	        			Player target = (Player)playerOrder.get(j);
	        			
	        			if(target.getTeam() != current.getTeam())
	        			{
	        				if(calcDist(current, target) <= c.getDistance() && !hasAttacked)
	        				{
	        					useWeapon(c.getName(), current, target, true);
		        				if(i >= tmpHand.size()) i--;
	        					
	        					tmpHand.remove(i);
		        				i--;
	        					if(j == myIndex)
	        					{
		        					resetCards();
		        		    		setCardImages();
	        					}
		        				break;
	        				}
	        			}
	        		}
	    		}
			}
    	}//for loop

		current.setInHands(tmpHand);
    }
    
    private int findLowestHP(Player current)
    {
    	int lowest = currentPlayer;
		for(int j=0; j < playerOrder.size(); j++)
		{
			Player target = (Player)playerOrder.get(j);
			
			if(target.getTeam() == current.getTeam() && target.getCurrentHP() < ((Player)playerOrder.get(lowest)).getCurrentHP())
			{
				lowest = j;
			}
		}
		
		return lowest;
    }
    
    private void discardAI()
    {
    	Vector tmp = ((Player)playerOrder.get(currentPlayer)).getInHands();
    	while(tmp.size() > Constants.AfterDiscardNumber)
    	{
    		tmp.remove(0);
    	}
    	((Player)playerOrder.get(currentPlayer)).setInHands(tmp);
    }
    
    private void checkPoison()
    {
    	Player current = (Player)playerOrder.get(currentPlayer);
    	if(current.getPoisonRound() > 0)
    	{
    		int prevHp = current.getCurrentHP();
    		current.poisonDamage();
    		int currHp = current.getCurrentHP();
    		
    		if(currHp < prevHp)
    		{
    			battleText = current.getpClass() + " suffer one damage from Poison!";
    		}
    	}
    }
    
    private void checkEnd()
    {
    	int myTeamHp = 0;
    	int enemyTeamHp = 0;
    	boolean isEnd = false;
    	
    	//TODO: may need to move updateHPImage
    	updateHPImage();
    	
    	for(int i = 0; i < playerOrder.size(); i++)
    	{
    		Player p = (Player)playerOrder.get(i);
    		
    		if(p.getCurrentHP() == 0 && p.getPlayerState().contains(Constants.ShallowName))
    		{
    			p.setCurrentHP(1);
    			p.getPlayerState().remove(Constants.ShallowName);
    		}
    		
    		if (p.getTeam() == me.getTeam())
    		{
    			myTeamHp += p.getCurrentHP();
    		}
    		else 
    		{
    			enemyTeamHp += p.getCurrentHP();
    		}
    		
    		if(p.getCurrentHP() <= 0)
    		{
				if(i == myIndex)
				{
					myIndex = -1;
    				inHands = new Vector();
    				setCardImages();
    				disableButtons();
				}
				
    			if(currentPlayer > i)
    			{
    				currentPlayer--;
    				
    				p.clearAllImages();
    				p.getPortrait().setBackgroundDrawable(getResources().getDrawable((Integer)playerDead.get(p.getpClass())));
    				playerOrder.remove(i);
    				i--;
    			}
    			else if (currentPlayer == i)
    			{
    				if(currentPlayer == myIndex)
    				{
        				me.clearAllImages();
        				me.getPortrait().setBackgroundDrawable(getResources().getDrawable((Integer)playerActive1.get(p.getpClass())));
        				changePhase();
    				}
    				else{
    					currentPhase = Constants.discardPhase;
    				}
    			}
    			else{

    				p.clearAllImages();
    				p.getPortrait().setBackgroundDrawable(getResources().getDrawable((Integer)playerActive1.get(p.getpClass())));
    				playerOrder.remove(i);
    				i--;
    			}
    			
    			myIndex = findIndex(me.getName(), playerOrder);
    		}
    	}
    	
    	if(myTeamHp <= 0 && enemyTeamHp <= 0)
    	{
        	thread.setState(thread.STATE_DRAW);
        	isEnd = true;
    	}
    	if(myTeamHp == 0)
    	{
    		thread.setState(thread.STATE_LOSE);
    		isEnd = true;
    	}
    	else if(enemyTeamHp <= 0)
    	{
    		thread.setState(thread.STATE_WIN);
    		isEnd = true;
    	}
    	
    	if(isEnd)
    	{
    		//TODO: enable this later
    		//backgroundMusic.stop();
	        thread.mHandler.sendMessage(thread.mHandler.obtainMessage());
    	}

    }
    
    private void updatePlayerImage(Player p)
	{
    	if (p.getSelected())
		{
			if(p.getTeam() == 1)
				p.getPortrait().setBackgroundDrawable(getResources().getDrawable((Integer)playerActive1.get(p.getpClass())));
			else
				p.getPortrait().setBackgroundDrawable(getResources().getDrawable((Integer)playerActive2.get(p.getpClass())));
		}
			
		else 
		{
			if(p.getTeam() == 1)
				p.getPortrait().setBackgroundDrawable(getResources().getDrawable((Integer)playerInactive1.get(p.getpClass())));
			else
				p.getPortrait().setBackgroundDrawable(getResources().getDrawable((Integer)playerInactive2.get(p.getpClass())));
		}
	}
    
    public void setPlayerImageHashtables(Hashtable h1, Hashtable h2, Hashtable h3, Hashtable h4)
    {
    	playerActive1 = h1;
    	playerInactive1 = h2;
    	playerActive2 = h3;
    	playerInactive2 = h4;
    }
    
    private int rollDice()
    {
    	return (int)(Constants.dice * Math.random()) + 1;
    }
    
    private void mySleep()
    {
    	try{
			Thread.sleep(Constants.threadSleepTime);
		}
		catch (Exception e)
		{
			
		}
    }
}
    
